﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using CommonControlLibrary.Common;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using DBAccessLibrary;
using ICSharpCode.AvalonEdit.CodeCompletion;
using DBAccessLibrary.Model;
using QueryResource.Common;
using QueryResource.ViewModel;
using System.Windows.Media;
using System.IO;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Folding;

namespace BaseControlLibrary
{
    /// <summary>
    /// SQLControl.xaml 的交互逻辑
    /// </summary>
    [System.ComponentModel.DesignTimeVisible(false)]
    public partial class SQLControl : DockPanel
    {
        //下拉窗口
        private CompletionWindow completionWindow;  
        //查找替换
        FindReplace.FindReplaceMgr FRM;
        private int _hashCode;//当前文本的哈希值
        private BaseXmlHelper _xmlHelper;
        public SQLControl()
        {
            InitializeComponent();
            ViewModel = new SqlViewModel {AppendText = AppendCmd};
            this.textEditor1.TextArea.TextEntered += textEditor_TextArea_TextEntered;
            this.textEditor1.TextArea.TextEntering += textEditor_TextArea_TextEntering;

            FRM = new FindReplace.FindReplaceMgr();
            FRM.CurrentEditor = new FindReplace.TextEditorAdapter(this.textEditor1);
            FRM.ShowSearchIn = false;
            //FRM.OwnerWindow = this;

            CommandBindings.Add(FRM.FindBinding);
            CommandBindings.Add(FRM.ReplaceBinding);
            CommandBindings.Add(FRM.FindNextBinding);
            Loaded += SqlControlLoaded;
            this.SizeChanged += SqlControlSizeChanged;

            _hashCode = string.Empty.GetHashCode();
        }
      
        #region 事件
        void SqlControlSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
        {
            //窗体大小改变时  滚动条始终在末尾
            //ScrollToEnd();
              DocumentLine line = this.textEditor1.Document.GetLineByOffset(textEditor1.CaretOffset);
              this.textEditor1.ScrollTo(line.LineNumber, line.Length);
            //this.textEditor1.ScrollToHorizontalOffset(this.textEditor1.CaretOffset);
            //this.textEditor1.ScrollToVerticalOffset(this.textEditor1.CaretOffset);
        }

        void SqlControlLoaded(object sender, System.Windows.RoutedEventArgs e)
        {
            //当窗体打开时  默认光标显示
            ThreadPool.QueueUserWorkItem(o =>
            {
                Thread.Sleep(300);
                this.InvokeEx(() => textEditor1.Focus());
                DispatcherHelper.DoEvents();
            });
            SettingInit();
        }

        private void textEditor1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F5)
            {
                //ViewModel.F5Command.Execute(null);
            }
            else if((e.KeyStates == Keyboard.GetKeyStates(Key.S) && Keyboard.Modifiers == ModifierKeys.Control) ||
               e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Down || e.Key == Key.Up ||
                Keyboard.Modifiers != ModifierKeys.None)
            {
            }
            else
            {
                ChangeContentAction(this.Tag, _hashCode != this.textEditor1.Text.GetHashCode());
            }

        }
        private void textEditor1_KeyUp(object sender, KeyEventArgs e)
        {
            //增加 通过快捷键来快速 拼接SQL语句
            if (e.Key == Key.Tab)
            {
                TabCaret();
            }
            ChangeContentAction(this.Tag ,_hashCode != this.textEditor1.Text.GetHashCode());
        }

        /// <summary>
        /// tab 快捷信息
        /// </summary>
        private void TabCaret()
        {

            string key;
            if (this.textEditor1.CaretOffset <= 2)
            {
                int index = this.textEditor1.CaretOffset - 2;
                if (index < 0)
                    return;
                key = this.textEditor1.Text.Substring(index, 1);
            }
            else
            {
                int index = this.textEditor1.CaretOffset - 3;
                key = this.textEditor1.Text.Substring(index, 2);
            }
            if (key.EndsWith("\t") || key.EndsWith("\n"))
            { return; }
            try
            {
                string repl = DBOperatorFactory.GetGrammar(SysCache.DBConnection).AppendTabText(key);

                if (repl != string.Empty)
                {
                    int count = key.Trim().Length + 1;
                    int index = this.textEditor1.CaretOffset - count;
                    textEditor1.Select(index, count);
                    textEditor1.SelectedText = repl;
                    textEditor1.Select(index + repl.Length, 0);
                }
            }
            catch (Exception ex)
            { }
        }
        private void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
        { 
            //查找出关键字
            //string content = this.textEditor1.Text.Substring(0, this.textEditor1.CaretOffset);
            switch (e.Text)
            {
                case ".":
                    {
                        #region TextEnteredPoint
                        //检索表实体
                        TableEntity table = ViewModel.TextEnteredPoint(this.textEditor1.Text, this.textEditor1.CaretOffset);
                        if (table != null)
                        {
                            completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                            IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                            foreach (FieldEntity field in table.FileNodes)
                            {
                                data.Add(new FieldCompletionData(field));
                            }
                            completionWindow.Show();
                            completionWindow.Closed += delegate
                            {
                                completionWindow = null;
                            };
                        }
                        #endregion
                    }
                    break;
                case " ":
                    {
                        #region TextEnteredSpace
                        IEnumerable<DataBaseEntity> list = ViewModel.TextEnteredSpace(this.textEditor1.Text, this.textEditor1.CaretOffset);
                        if (list != null)
                        {
                            completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                            IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                            foreach (DataBaseEntity table in list)
                            {
                                data.Add(new FieldCompletionData(table));
                            }
                            completionWindow.CloseAction = obj =>
                            {
                                FieldCompletionData field = obj as FieldCompletionData;
                                if (field != null)
                                {
                                    string text = DBOperatorFactory.GetGrammar(SysCache.DBConnection).GetProcParamInfo(field.DBEntity as ProcEntity);
                                    if (!string.IsNullOrEmpty(text))
                                    {
                                        int index = text.IndexOf('(');
                                        if(index > 0)
                                            this.AppendCaretCmd(text.Substring(index));
                                    }
                                }
                            };
                            completionWindow.Show();
                            completionWindow.Closed += delegate
                            {
                                completionWindow = null;
                            };
                        }
                        #endregion
                    }
                    break;
                case ",":
                    {
                        #region TextEnteredComma
                        IEnumerable<DataBaseEntity> list = ViewModel.TextEnteredComma(this.textEditor1.Text, this.textEditor1.CaretOffset);
                        if (list != null)
                        {
                            completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                            IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                            foreach (DataBaseEntity table in list)
                            {
                                data.Add(new FieldCompletionData(table));
                            }
                            completionWindow.Show();
                            completionWindow.Closed += delegate
                            {
                                completionWindow = null;
                            };
                        }
                        #endregion
                    }
                    break;
            }
           
        }

        private void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e)
        {
            //if (e.Text.Length > 0 && completionWindow != null)
            //{
            //    if (!char.IsLetterOrDigit(e.Text[0]))
            //    {
            //        completionWindow.CompletionList.RequestInsertion(e);
            //    }
            //}
        }
        //格式刷
        private void Format_CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !string.IsNullOrEmpty(ViewModel.SelectText);
        }
        private void Format_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.textEditor1.SelectedText = ViewModel.SqlFormatPainter(this.textEditor1.SelectedText, true);
        }
        //转换成C# 拼接语句
        private void Splice_CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !string.IsNullOrEmpty(ViewModel.SelectText);
        }
        private void Splice_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ViewModel.SqlSplicePainter();
        }
      
        //定位
        private void Position_CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //如果所选择的内容是表名 则可用
            //e.CanExecute = ViewModel.IsPositionTable;
            e.CanExecute = true;
        }
        private void Position_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //定位到 树中该节点
            ViewModel.PositionTable();
        }
        //智能提示
        private void Query_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //显示所有表
            ShowAllTable();
        }
        //注释
        public void Comment_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            
            int startOffset = this.textEditor1.CaretOffset;
            if (this.textEditor1.SelectedText != string.Empty)
            {
                startOffset = this.textEditor1.SelectionStart;
            }


            DocumentLine line = this.textEditor1.Document.GetLineByOffset(startOffset);
           
            int end = this.textEditor1.CaretOffset;

            while (line.Offset <= end)
            {
                string text = this.textEditor1.Document.GetText(line.Offset, line.EndOffset - line.Offset);

                if (!text.TrimStart().StartsWith("--"))
                {
                    this.textEditor1.Document.Insert(line.Offset, "--");
                }
                line = line.NextLine;
                if (line == null)
                    break;
            }
            ChangeContentAction(this.Tag, _hashCode != this.textEditor1.Text.GetHashCode());
        }
        //反注释
        public void NoComment_CommandBinding_Excuted(object sender, ExecutedRoutedEventArgs e)
        {
          
            int startOffset = this.textEditor1.CaretOffset;
            if (this.textEditor1.SelectedText != string.Empty)
            {
                startOffset = this.textEditor1.SelectionStart;
            }


            DocumentLine line = this.textEditor1.Document.GetLineByOffset(startOffset);
            if (line == null)
                return;

            int end = this.textEditor1.CaretOffset;

            while (line.Offset <= end)
            {
                string text = this.textEditor1.Document.GetText(line.Offset, line.EndOffset - line.Offset);

                if (text.TrimStart().StartsWith("--"))
                {
                    int index = text.IndexOf("--", StringComparison.CurrentCulture);
                    if(index != -1)
                    {
                        this.textEditor1.Document.Remove(line.Offset + index, 2);
                    }
                }
                line = line.NextLine;
                if (line == null)
                    break;
            }
            ChangeContentAction(this.Tag, _hashCode != this.textEditor1.Text.GetHashCode());
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 读取配置信息
        /// </summary>
        private void SettingInit()
        {
            _xmlHelper = new BaseXmlHelper();
            string fName = _xmlHelper.FontName;
            if (!string.IsNullOrEmpty(fName))
            {
                this.textEditor1.FontFamily = new FontFamily(fName);
            }
            else
            {
                _xmlHelper.FontName = this.textEditor1.FontFamily.Source;
            }
            string fSize = _xmlHelper.FontSize;
            if (!string.IsNullOrEmpty(fSize))
            {
                try
                {
                    this.textEditor1.FontSize = Convert.ToDouble(fSize);
                }
                catch
                {
                }
            }
            else
            {
                _xmlHelper.FontSize = this.textEditor1.FontSize.ToString(CultureInfo.InvariantCulture);
            }
            bool isFolding = _xmlHelper.IsFloding;
            if (isFolding)
            {
                FoldingStart();
            }
            _xmlHelper.FoldingChange = flag =>
            {
                if (flag)
                    FoldingStart();
                else
                    FoldingStop();
            };
            _xmlHelper.FontNameChange = fontName => this.textEditor1.FontFamily = new FontFamily(fontName);
            _xmlHelper.FontSizeChange = fontSize => this.textEditor1.FontSize = fontSize;

        }
        /// <summary>
        /// 显示智能提示 表信息
        /// </summary>
        private void ShowAllTable()
        {
            IEnumerable<DataBaseEntity> list = SysCache.TableList;
            if (list != null)
            {
                completionWindow = new CompletionWindow(this.textEditor1.TextArea);
                IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
                foreach (DataBaseEntity table in list)
                {
                    data.Add(new FieldCompletionData(table));
                }
                completionWindow.Show();
                completionWindow.Closed += delegate
                {
                    completionWindow = null;
                };
            }
        }
        #endregion

        #region 公共方法
        public void Init(bool isLoadFile, bool isScollToEnd = true)
        {

            ViewModel.GetFontName = () => this.textEditor1.FontFamily.Source;
            ViewModel.GetFontSize = () => this.textEditor1.FontSize;
            ViewModel.GetMaxWidth = () => this.textEditor1.ViewportWidth;
            ViewModel.GetSelectText = () => this.textEditor1.SelectedText;
            ViewModel.SetSelectText = text => this.textEditor1.SelectedText = text;

            this.DataContext = ViewModel;

            this.textEditor1.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("SQL");
            if (isLoadFile)
            {
                if (File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + "\\文档.txt"))
                {
                    this.LoadFile(System.AppDomain.CurrentDomain.BaseDirectory + "\\文档.txt");
                    if (isScollToEnd)
                    {
                        ScrollToEnd();
                    }
                }
            }
        }
        public SqlViewModel ViewModel { get; set; }
        /// <summary>
        /// 是否是新建（如果新建需要保存）
        /// </summary>
        public bool IsNewDocument { get; set; }
        public string FilePath { get; set; }

        /// <summary>
        /// 读取文件的数据
        /// </summary>
        /// <param name="filePath"></param>
        public void LoadFile(string filePath)
        {
            if (!string.IsNullOrEmpty(filePath))
            {
                this.textEditor1.Load(filePath);
                this.FilePath = filePath;
                _hashCode = this.textEditor1.Text.GetHashCode();
            }
        }
        public void LoadText(string text)
        {
            _hashCode = text.GetHashCode();
            AppendCmd(text);
        }
        /// <summary>
        /// 保存数据到文件
        /// </summary>
        /// <param name="fileName"></param>
        public void SaveFile(string fileName)
        {
            if (!string.IsNullOrEmpty(fileName))
            {
                string dirpath = Path.GetDirectoryName(fileName);
                if (!string.IsNullOrEmpty(dirpath) && !Directory.Exists(dirpath))
                {
                    Directory.CreateDirectory(dirpath);
                }
                if (string.IsNullOrEmpty(Path.GetExtension(fileName)))
                {
                    fileName += ".txt";
                }
                this.textEditor1.Save(fileName);
                _hashCode = this.textEditor1.Text.GetHashCode();
            }
        }
        /// <summary>
        /// 删除新建文件
        /// </summary>
        public void RemoveFile()
        {
            if (IsNewDocument)
            {
                string filename = System.AppDomain.CurrentDomain.BaseDirectory + "\\Temporary\\" + FilePath;
                if (File.Exists(filename))
                {
                    if (MessageBox.Show("是否需要删除该文件?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK)
                    {
                        File.Delete(filename);
                    }
                }
            }
        }
        /// <summary>
        /// 换行 添加信息到末尾
        /// </summary>
        /// <param name="msg"></param>
        public void AppendCmd(string msg)
        {
            this.textEditor1.BeginInvokeEx(() =>
                                               {
                                                   this.textEditor1.AppendText(msg);
                                                   ScrollToEnd();
                                                   ChangeContentAction(this.Tag, _hashCode != this.textEditor1.Text.GetHashCode());
                                               });
        }
        /// <summary>
        /// 添加信息到光标处
        /// </summary>
        /// <param name="msg"></param>
        public void AppendCaretCmd(string msg)
        {
            this.textEditor1.BeginInvokeEx(() => this.textEditor1.AppendOfficeText(msg));
        }
        /// <summary>
        /// 光标移动到末尾
        /// </summary>
        private void ScrollToEnd()
        {
            this.textEditor1.ScrollToEnd();
            this.textEditor1.CaretOffset = this.textEditor1.Text.Length;
        }
        /// <summary>
        /// 清空
        /// </summary>
        public void Clear()
        {
            this.textEditor1.SelectAll();
            this.textEditor1.SelectedText = string.Empty;
        }
        /// <summary>
        /// 是否有内容
        /// </summary>
        public bool IsTxtContent
        {
            get { return this.textEditor1.Text != string.Empty; }
        }

        public void Dispose()
        {
            ViewModel.AppendLogAction = null;
            ViewModel.AppendDataAction = null;
            ViewModel.AppendText = null;
            ViewModel = null;

            RemoveFile();

            ChangeContentAction = null;
            completionWindow = null;
            FRM = null;
            
            if(foldingUpdateTimer!= null)
            {
                foldingUpdateTimer.Stop();
                foldingUpdateTimer = null;
            }
        }

        #endregion

        #region 外部交互

        public Action<object,bool> ChangeContentAction { get; set; }

        #endregion

        #region 折叠
        FoldingManager foldingManager;
        AbstractFoldingStrategy foldingStrategy;
        private DispatcherTimer foldingUpdateTimer;
        private void FoldingStart()
        {
            if (foldingUpdateTimer == null)
            {
                foldingUpdateTimer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(2)};
                foldingUpdateTimer.Tick += foldingUpdateTimer_Tick;

                this.textEditor1.TextArea.IndentationStrategy =
             new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy(textEditor1.Options);
            }
            if(!foldingUpdateTimer.IsEnabled)
            {
                foldingUpdateTimer.Start();
                foldingStrategy = new SqlFoldingStrategy();
                if (foldingManager == null)
                    foldingManager = FoldingManager.Install(this.textEditor1.TextArea);

            }
        }

        private void FoldingStop()
        {
            if (foldingUpdateTimer == null)
                return;
            foldingUpdateTimer.Stop();
            if (foldingManager != null)
            {
                FoldingManager.Uninstall(foldingManager);
                foldingManager = null;
            }
        }

        void foldingUpdateTimer_Tick(object sender, EventArgs e)
        {
            if (foldingStrategy != null)
            {
                foldingStrategy.UpdateFoldings(foldingManager, this.textEditor1.Document.Text);
            }
        }
        #endregion
    }
}
